package com.study.common;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

/**Redis缓存的通用配置类
 * 	在mappers/*.xml中进行引用即可
 *	redis工作的情况都我写入日志logger中，可以在控制台信息中进行跟踪查看
 * @author WuJin
 *
 */
public class RedisCache implements Cache {
	private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);

	private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

	private String id;

	@SuppressWarnings("rawtypes")
	private RedisTemplate redisTemplate;

	private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间

	public RedisCache(String id) {
		if (id == null) {
			throw new IllegalArgumentException("Cache instances require an ID----缓存实例需要ID");
		}
		this.id = id;
	}

	@Override
	public String getId() {
		return id;
	}

	/**将查询结果放入
	 * redis Put query result to redis
	 * @param key
	 * @param value
	 */
	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void putObject(Object key, Object value) {
		try {
			RedisTemplate redisTemplate = getRedisTemplate();
			ValueOperations opsForValue = redisTemplate.opsForValue();
			opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
			logger.error("结果存入redis缓存中......");
		} catch (Exception e) {
			System.out.println(e);
			logger.error("结果存入redis缓存失败......", e);
		}
	}

	/**从redis获取缓存查询结果
	 * Get cached query result from redis
	 * @param key
	 * @return
	 */
	@Override
	@SuppressWarnings({ "rawtypes" })
	public Object getObject(Object key) {
		try {
			RedisTemplate redisTemplate = getRedisTemplate();
			ValueOperations opsForValue = redisTemplate.opsForValue();
			logger.error("成功从redis缓存中获取结果......");
			return opsForValue.get(key);
		} catch (Throwable t) {
			logger.error("获取结果到缓存失败......", t);
			return null;
		}
	}

	/**从redis中删除缓存的查询结果
	 * Remove cached query result from redis
	 * @param key
	 * @return
	 */
	@Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public Object removeObject(Object key) {
		try {
			RedisTemplate redisTemplate = getRedisTemplate();
			redisTemplate.delete(key);
			logger.debug("缓存被删除......");
		} catch (Throwable t) {
			logger.error("删除缓存失败......");
		}
		return null;
	}

	/**清除此缓存实例
	 * Clears this cache instance
	 */
	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void clear() {
		RedisTemplate redisTemplate = getRedisTemplate();
		redisTemplate.execute((RedisCallback) connection -> {
			connection.flushDb();
			return null;
		});
		logger.debug("缓存被清空了......");
	}

	/**不使用此方法
	 * This method is not used
	 * @return
	 */
	@Override
	public int getSize() {
		return 0;
	}

	@Override
	public ReadWriteLock getReadWriteLock() {
		return readWriteLock;
	}

	@SuppressWarnings("rawtypes")
	private RedisTemplate getRedisTemplate() {
		if (redisTemplate == null) {
			// 因为redis不是Spring的Bean对象，不受容器管理，不能使用Autoriwed
			redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
		}
		return redisTemplate;
	}

}
